#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include "expand.hpp"
#include "exec_context.hpp"

#include <boost/assign/list_of.hpp>
#include <boost/timer.hpp>
using boost::assign::list_of;

//Test simple variable expansion
BOOST_AUTO_TEST_CASE(expand_test_0)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;
	jam_list val;
	expand_string(args,ctx,"Hello, world!",val);
	BOOST_CHECK(val.size() == 1);
	BOOST_CHECK(val.front() == "Hello, world!");
}

//Test simple variable substitution
BOOST_AUTO_TEST_CASE(expand_test_1)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;
		
	ctx.set_var_value("a",jam_list("test"));
	jam_list val;
	expand_string(args,ctx,"Hello: $(a)!",val); //Hello: $(a)
	BOOST_CHECK(val.size() == 1);
	BOOST_CHECK(val.front() == "Hello: test!");
}

//Test Cartesian product expansion
BOOST_AUTO_TEST_CASE(expand_test_2)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;

	ctx.set_var_value("a", list_of<jam_string>("1")("2"));
	ctx.set_var_value("b", list_of<jam_string>("a")("b"));
	ctx.set_var_value("c",jam_list("!"));
	jam_list etalon=list_of("Hello: 1, a!")("Hello: 1, b!")("Hello: 2, a!")("Hello: 2, b!");
	
	jam_list val;
	expand_string(args,ctx,"Hello: $(a), $(b)$(c)",val);	
	BOOST_CHECK(val.size() == 4);
	BOOST_CHECK(val == etalon);
}

//Test embedded variables:
//c = 2 ;
//b = "1" "$(c)" ;
//a = "$(b)" ;
//var1 = 2 ;
//var2 = 4 ;
//ECHO "Test: $(var$(a))" ;
BOOST_AUTO_TEST_CASE(expand_test_3)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;

	ctx.set_var_value("c",jam_list("2"));
	ctx.set_var_value("b",list_of<jam_string>("1")("$(c)"));
	ctx.set_var_value("a",jam_list("$(b)"));
	ctx.set_var_value("var1",jam_list("2"));
	ctx.set_var_value("var2",jam_list("4"));
	jam_list etalon=list_of("Test: 2!")("Test: 4!");

	jam_list val;
	expand_string(args,ctx,boost::cref("Test: $(var$(a))!"),val);
	BOOST_CHECK(val.size() == 2);
	BOOST_CHECK(val == etalon);
}

//Test embedded variable with one empty expansion:
//c = none ;
//b = "1" "$(c)" ;
//a = "$(b)" ;
//var1 = 2 ;
//var2 = 4 ;
//ECHO "Test: $(var$(a)) $(var2) $(var2)!" ;
BOOST_AUTO_TEST_CASE(expand_test_4)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;

	ctx.set_var_value("c",jam_list("none"));
	ctx.set_var_value("b",list_of<jam_string>("1")("$(c)"));
	ctx.set_var_value("a",jam_list("$(b)"));
	ctx.set_var_value("var1",jam_list("2"));
	ctx.set_var_value("var2",jam_list("4"));
	jam_list etalon=list_of("Test: 2 4 4!");

	jam_list val;
	expand_string(args,ctx,"Test: $(var$(a)) $(var2) $(var2)!",val);
	BOOST_CHECK(val.size() == 1);
	BOOST_CHECK(val == etalon);	
}

//Test quoting
BOOST_AUTO_TEST_CASE(expand_test_5)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;

	ctx.set_var_value("some",jam_list("not some"));

	jam_list val;
	expand_string(args,ctx,"\\$\\(some\\) is $(some)",val);	
	BOOST_CHECK(val.size() == 1);
	BOOST_CHECK(val.front() == "\\$\\(some\\) is not some");
}

//Test function arguments support
BOOST_AUTO_TEST_CASE(expand_test_6)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;

	args=list_of(jam_list("1"))
		(jam_list("2"))(jam_list("3"))
		(jam_list("4"));

	jam_list val;
	expand_string(args,ctx,"$(>) $(<) $(1) $(3)",val);	
	BOOST_CHECK(val.size() == 1);
	BOOST_CHECK(val.front() == "2 1 1 3");
}

//Test modifiers
BOOST_AUTO_TEST_CASE(expand_test_7)
{
	jam_module ctx(NULL,false,"NoName");
	list_of_lists args;

	ctx.set_var_value("c",jam_list("none"));

	jam_list val;
	expand_string(args,ctx,"$(c[1]:U)",val);
	std::cout<<val<<std::endl;
	BOOST_CHECK(val.size() == 1);
	BOOST_CHECK(val.front() == "none");
}
